package com.zjl.redis.第04章_事务_管道_发布订阅;

import com.zjl.redis.第01章_redis安装.RedisUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Transaction;

import java.util.List;

/**
 * 管道 pipelining
 *   如果同时需要执行大量的命令那么就要等待上一条命令应答后再执行，
 *   这中间不仅仅多了RTT (Round Time Trip)，而且还频繁调用系统IO，发送网络请求，
 *   同时需要redis调用多次read()和write()系统方法，
 *   系统方法会将数据从用户态转移到内核态，这样就会对进程上下文有比较大的影响了，性能不太好，
 *
 * 管道(pipeline)可以一次性发送多条命令给服务端，服务端依次处理完完毕后，
 * 通过一条响应一次性将结果返回，通过减少客户端与redis的通信次数来实现降低往返延时时间。
 * pipeline 实现的原理是队列，先进先出特性就保证数据的顺序性。
 *
 *
 * cat cmd.txt | redis-cli -h ip -a 密码 -p 6379 --pipe
 * 在linux中 直接将 cmd.txt 文件读取的内容传递到 redis中，用 pipe（管道）执行命令
 *
 * pipeline缓冲的指令只是会依次执行，不保证原子性，
 *      如果执行中指令发生异常，将会继续执行后续的指令
 * 使用pipeline组装的命令个数不能太多，不然数据量过大客户端阻塞的时间可能过久，
 *      同时服务端此时也被迫回复一个队列答复，占用很多内存
 *
 *
 *
 */
public class B1_管道 {
    public static void main(String[] args) throws InterruptedException {

        Jedis redis = RedisUtil.getRedisPool();
        //管道
        Pipeline pipelined = redis.pipelined();
        pipelined.set("k1","v1");
        pipelined.set("k2","v2");
        pipelined.set("k3","v3");
        //再执行管道时，不能使用 Jedis 进行 redis的访问，需要另起一个连接
        System.out.println(RedisUtil.getRedisPool().set("k3","v33"));
        System.out.println(RedisUtil.getRedisPool().get("k3"));
        pipelined.set("k4","v4");
        pipelined.set("k5","v5");
        pipelined.set("k6","v6");
        List<Object> objects = pipelined.syncAndReturnAll();
        System.out.println(objects);
        redis.close();//关闭

    }

}
